# Set matplotlib backend for headless plotting
import matplotlib
matplotlib.use('Agg')

Plotting mass loss over time

Loading data & defining get_stats

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats

# # Path to Excel file - use relative path for portability
# file_path = "../MassLoss_processing/massLossDataProcessing.xlsx"

# Path to Excel file from local repository
import os
box_base = os.environ.get('BOX_BASE')
if box_base is None:
    raise ValueError("BOX_BASE environment variable is not set!")

file_path = os.path.join(box_base, "Salk Institute Project/AKS Salk files/MassLoss_processing/massLossDataProcessing.xlsx")

# Read the 'toPlot' sheet
df = pd.read_excel(file_path, sheet_name='toPlot')

# Rename columns for clarity
df['litterbag mass remaining (%)'] = df['lb_remaining_perc._corr.']
df['sifted root mass remaining (%)'] = df['root_remaining_perc._corr.']
df['litterbag mass remaining (mg)'] = df['lb_remaining_mg_corr.']
df['sifted root mass remaining (mg)'] = df['root_remaining_mg_corr.']
df['litterbag mass remaining new (%)'] = df['lb_remaining_perc._corr.2']
print(df.head())

# Function to calculate statistics
def get_stats(data, value_col):
    stats_df = data.groupby(['Isotope', 'Crop'])[value_col].agg(['mean', 'std', 'count', 'min', 'max', 'median']).reset_index()
    return stats_df

# Define crop colors
crop_colors = {'noPlant': '#9F29FF', 'wheat': '#98C65D', 'rice': '#FC9D33', 'soy': '#FE318E'}
>    Sample_number  ...  litterbag mass remaining new (%)
> 0              1  ...                             100.0
> 1              2  ...                             100.0
> 2              3  ...                             100.0
> 3              4  ...                             100.0
> 4              5  ...                             100.0
> 
> [5 rows x 15 columns]

Litterbag mass remaining over time - percent

# Plot 1: remaining/noPlant_percent vs Week, grouped by Isotope and Crop
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='litterbag mass remaining (%)', hue='Crop', style='Isotope', markers=True, palette=crop_colors)
plt.title('Litterbag Mass Remaining (%) vs Time (weeks) (Grouped by Isotope and Crop)')
plt.xlabel('Time (weeks)')
plt.ylabel('Litterbag Mass Remaining (%)')
plt.legend(title='Isotope / Crop')
plt.show()

# Statistics for Plot 1
stats_df1 = get_stats(df, 'litterbag mass remaining (%)')
print("Statistics for Plot 1:\n", stats_df1)

# Plot 2: remaining/noPlant_percent vs Time (weeks), grouped by Crop only
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='litterbag mass remaining (%)', hue='Crop', marker='o', palette=crop_colors)
plt.title('Litterbag Mass Remaining (%) vs Time (weeks) (Grouped by Crop Only)')
plt.xlabel('Time (weeks)')
plt.ylabel('Litterbag Mass Remaining (%)')
plt.legend(title='Crop')
plt.show()

# Statistics for Plot 2
stats_df2 = get_stats(df, 'litterbag mass remaining (%)')
print("Statistics for Plot 2:\n", stats_df2)

> Statistics for Plot 1:
>     Isotope     Crop        mean  ...        min         max  median
> 0       12  noPlant  102.074571  ...  94.928072  137.760416   100.0
> 1       12     rice  110.644934  ...  92.338602  189.561282   100.0
> 2       12      soy  103.722970  ...  80.566872  166.900554   100.0
> 3       13     rice  109.016668  ...  86.892651  174.279573   100.0
> 4       13      soy  107.833936  ...  81.260888  252.242054   100.0
> 5       13    wheat  104.122333  ...  87.229973  199.754897   100.0
> 
> [6 rows x 8 columns]

> Statistics for Plot 2:
>     Isotope     Crop        mean  ...        min         max  median
> 0       12  noPlant  102.074571  ...  94.928072  137.760416   100.0
> 1       12     rice  110.644934  ...  92.338602  189.561282   100.0
> 2       12      soy  103.722970  ...  80.566872  166.900554   100.0
> 3       13     rice  109.016668  ...  86.892651  174.279573   100.0
> 4       13      soy  107.833936  ...  81.260888  252.242054   100.0
> 5       13    wheat  104.122333  ...  87.229973  199.754897   100.0
> 
> [6 rows x 8 columns]

Trying another correction

Dividing the percent mass remaining by the average T0 percent remaining (after 2 days), grouped by Isotope and Crop. Previous chunk divided by average noPlant mass remaining (across all time points).

# Plot 1: remaining/noPlant_percent vs Week, grouped by Isotope and Crop
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='litterbag mass remaining new (%)', hue='Crop', style='Isotope', markers=True, palette=crop_colors)
plt.title('Litterbag Mass Remaining (%) vs Time (weeks) (Grouped by Isotope and Crop)')
plt.xlabel('Time (weeks)')
plt.ylabel('Litterbag Mass Remaining (%)')
plt.legend(title='Isotope / Crop')
plt.show()

# Statistics for Plot 1
stats_dfn = get_stats(df, 'litterbag mass remaining new (%)')
print("Statistics for Plot 1:\n", stats_dfn)

# Plot 2: remaining/noPlant_percent vs Time (weeks), grouped by Crop only
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='litterbag mass remaining new (%)', hue='Crop', marker='o', palette=crop_colors)
plt.title('Litterbag Mass Remaining (%) vs Time (weeks) (Grouped by Crop Only)')
plt.xlabel('Time (weeks)')
plt.ylabel('Litterbag Mass Remaining (%)')
plt.legend(title='Crop')
plt.show()

# Statistics for Plot 2
stats_dfn1 = get_stats(df, 'litterbag mass remaining new (%)')
print("Statistics for Plot 2:\n", stats_dfn1)

> Statistics for Plot 1:
>     Isotope     Crop        mean  ...        min         max  median
> 0       12  noPlant  101.133742  ...  93.213011  135.271505   100.0
> 1       12     rice  106.531191  ...  86.074974  176.702723   100.0
> 2       12      soy  101.611298  ...  77.400055  160.340246   100.0
> 3       13     rice   90.602930  ...  59.781352  119.902757   100.0
> 4       13      soy   81.952333  ...  44.895353  139.359738   100.0
> 5       13    wheat   87.889272  ...  61.066846  139.841858   100.0
> 
> [6 rows x 8 columns]

> Statistics for Plot 2:
>     Isotope     Crop        mean  ...        min         max  median
> 0       12  noPlant  101.133742  ...  93.213011  135.271505   100.0
> 1       12     rice  106.531191  ...  86.074974  176.702723   100.0
> 2       12      soy  101.611298  ...  77.400055  160.340246   100.0
> 3       13     rice   90.602930  ...  59.781352  119.902757   100.0
> 4       13      soy   81.952333  ...  44.895353  139.359738   100.0
> 5       13    wheat   87.889272  ...  61.066846  139.841858   100.0
> 
> [6 rows x 8 columns]

Root mass remaining over time - percent

# Plot 3: remaining_root/cleanBag_percent vs Time (weeks), grouped by Isotope and Crop
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='sifted root mass remaining (%)', hue='Crop', style='Isotope', markers=True, palette=crop_colors)
plt.title('Sifted Root Mass Remaining (%) vs Time (weeks) (Grouped by Isotope and Crop)')
plt.xlabel('Time (weeks)')
plt.ylabel('Sifted Root Mass Remaining (%)')
plt.legend(title='Isotope / Crop')
plt.show()

# Statistics for Plot 3
stats_df3 = get_stats(df, 'sifted root mass remaining (%)')
print("Statistics for Plot 3:\n", stats_df3)

# Plot 4: remaining_root/cleanBag_percent vs Time (weeks), grouped by Crop only
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='sifted root mass remaining (%)', hue='Crop', marker='o', palette=crop_colors)
plt.title('Sifted Root Mass Remaining (%) vs Time (weeks) (Grouped by Crop Only)')
plt.xlabel('Time (weeks)')
plt.ylabel('Sifted Root Mass Remaining (%)')
plt.legend(title='Crop')
plt.show()

# Statistics for Plot 4
stats_df4 = get_stats(df, 'sifted root mass remaining (%)')
print("Statistics for Plot 4:\n", stats_df4)

> Statistics for Plot 3:
>     Isotope     Crop        mean  ...         min         max  median
> 0       12  noPlant  100.000000  ...  100.000000  100.000000   100.0
> 1       12     rice  100.840695  ...   92.035454  125.097049   100.0
> 2       12      soy   99.786563  ...   92.665753  103.155015   100.0
> 3       13     rice  100.000000  ...  100.000000  100.000000   100.0
> 4       13      soy  100.000000  ...  100.000000  100.000000   100.0
> 5       13    wheat  100.000000  ...  100.000000  100.000000   100.0
> 
> [6 rows x 8 columns]

> Statistics for Plot 4:
>     Isotope     Crop        mean  ...         min         max  median
> 0       12  noPlant  100.000000  ...  100.000000  100.000000   100.0
> 1       12     rice  100.840695  ...   92.035454  125.097049   100.0
> 2       12      soy   99.786563  ...   92.665753  103.155015   100.0
> 3       13     rice  100.000000  ...  100.000000  100.000000   100.0
> 4       13      soy  100.000000  ...  100.000000  100.000000   100.0
> 5       13    wheat  100.000000  ...  100.000000  100.000000   100.0
> 
> [6 rows x 8 columns]

Litterbag mass remaining over time - milligrams

# Plot 5: remaining root mass (mg) vs Time (weeks), grouped by Isotope and Crop
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='litterbag mass remaining (mg)', hue='Crop', style='Isotope', markers=True, palette=crop_colors)
plt.title('Litterbag Mass Remaining (mg) vs Time (weeks) (Grouped by Isotope and Crop)')
plt.xlabel('Time (weeks)')
plt.ylabel('Litterbag Mass Remaining (mg)')
plt.legend(title='Isotope / Crop')
plt.show()

# Statistics for Plot 5
stats_df5 = get_stats(df, 'litterbag mass remaining (mg)')
print("Statistics for Plot 5:\n", stats_df5)

# Plot 6: remaining root mass (mg) vs Time (weeks), grouped by Crop only
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='litterbag mass remaining (mg)', hue='Crop', marker='o', palette=crop_colors)
plt.title('Litterbag Mass Remaining (mg) vs Time (weeks) (Grouped by Crop Only)')
plt.xlabel('Time (weeks)')
plt.ylabel('Litterbag Mass Remaining (mg)')
plt.legend(title='Crop')
plt.show()

# Statistics for Plot 6
stats_df6 = get_stats(df, 'litterbag mass remaining (mg)')
print("Statistics for Plot 6:\n", stats_df6)

> Statistics for Plot 5:
>     Isotope     Crop        mean  ...         min         max      median
> 0       12  noPlant   71.685531  ...   66.931674   97.534375   70.150000
> 1       12     rice  159.552628  ...  133.863348  254.959924  144.900000
> 2       12      soy  146.960662  ...  114.243825  237.499488  142.050000
> 3       13     rice  155.774256  ...  122.692423  247.825552  143.050000
> 4       13      soy  145.050531  ...  116.215164  313.536873  133.250054
> 5       13    wheat  101.186028  ...   85.049224  179.579652   96.650000
> 
> [6 rows x 8 columns]

> Statistics for Plot 6:
>     Isotope     Crop        mean  ...         min         max      median
> 0       12  noPlant   71.685531  ...   66.931674   97.534375   70.150000
> 1       12     rice  159.552628  ...  133.863348  254.959924  144.900000
> 2       12      soy  146.960662  ...  114.243825  237.499488  142.050000
> 3       13     rice  155.774256  ...  122.692423  247.825552  143.050000
> 4       13      soy  145.050531  ...  116.215164  313.536873  133.250054
> 5       13    wheat  101.186028  ...   85.049224  179.579652   96.650000
> 
> [6 rows x 8 columns]

Root mass remaining over time - milligrams

# Plot 7: remaining root mass (mg) vs Time (weeks), grouped by Isotope and Crop
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='sifted root mass remaining (mg)', hue='Crop', style='Isotope', markers=True, palette=crop_colors)
plt.title('Sifted Root Mass Remaining (mg) vs Time (weeks) (Grouped by Isotope and Crop)')
plt.xlabel('Time (weeks)')
plt.ylabel('Sifted Root Mass Remaining (mg)')
plt.legend(title='Isotope / Crop')
plt.show()

# Statistics for Plot 7
stats_df7 = get_stats(df, 'sifted root mass remaining (mg)')
print("Statistics for Plot 7:\n", stats_df7)

# Plot 8: remaining root mass (mg) vs Time (weeks), grouped by Crop only
plt.figure(figsize=(12, 8))
sns.lineplot(data=df, x='Time (weeks)', y='sifted root mass remaining (mg)', hue='Crop', marker='o', palette=crop_colors)
plt.title('Sifted Root Mass Remaining (mg) vs Time (weeks) (Grouped by Crop Only)')
plt.xlabel('Time (weeks)')
plt.ylabel('Sifted Root Mass Remaining (mg)')
plt.legend(title='Crop')
plt.show()

# Statistics for Plot 8
stats_df8 = get_stats(df, 'sifted root mass remaining (mg)')
print("Statistics for Plot 8:\n", stats_df8)

> Statistics for Plot 7:
>     Isotope     Crop       mean        std  count   min         max  median
> 0       12  noPlant   0.313593   0.863657     20   0.0    3.462379    0.00
> 1       12     rice  74.966245   7.570415     20  63.8  103.079968   73.85
> 2       12      soy  71.199356   4.227155     20  63.4   83.300000   71.35
> 3       13     rice  72.187500   2.496364     16  68.3   77.600000   72.10
> 4       13      soy  64.856250  10.100097     16  53.5   92.300000   62.25
> 5       13    wheat  26.862500   5.868546     16  19.1   39.100000   25.95

> Statistics for Plot 8:
>     Isotope     Crop       mean        std  count   min         max  median
> 0       12  noPlant   0.313593   0.863657     20   0.0    3.462379    0.00
> 1       12     rice  74.966245   7.570415     20  63.8  103.079968   73.85
> 2       12      soy  71.199356   4.227155     20  63.4   83.300000   71.35
> 3       13     rice  72.187500   2.496364     16  68.3   77.600000   72.10
> 4       13      soy  64.856250  10.100097     16  53.5   92.300000   62.25
> 5       13    wheat  26.862500   5.868546     16  19.1   39.100000   25.95